package com.dys.ai.service.impl;

import com.dys.ai.common.api.ApiResponse;
import com.dys.ai.common.api.ResponseEntity;
import com.dys.ai.common.dto.BookingDetailsDTO;
import com.dys.ai.common.dto.OrderDTO;
import com.dys.ai.common.enumeration.SeatTypeEnum;
import com.dys.ai.common.exception.CustomException;
import com.dys.ai.entity.*;
import com.dys.ai.mapper.*;
import com.dys.ai.service.TicketService;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.List;

/**
 * @author 疾风
 */
@Service
public class TicketServiceImpl implements TicketService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private SeatMapper seatMapper;

    @Autowired
    private CarriageMapper carriageMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private TrainMapper trainMapper;

    @Autowired
    private TicketChangeMapper ticketChangeMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseEntity butTicketByUserInput(String realName, String departureStation, String arrivalStation, LocalTime departureDate, String trainNumber, String seatTypeName) {
        // 1. 验证用户存在
        User user = userMapper.getUserInfoByRealName(realName);
        if (user == null) {
            throw new CustomException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "用户不存在");
        }

        // 2. 查询车次（通过车次号、出发站、到达站、日期）
        Train train = trainMapper.getTrainByCriteria(
                trainNumber,
                departureStation,
                arrivalStation,
                departureDate
        );
        if (train == null) {
            throw new CustomException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "车次不存在或信息不匹配");
        }

        // 3. 转换座位类型名称为代码
        SeatTypeEnum seatType = SeatTypeEnum.fromName(seatTypeName);
        int seatCode = seatType.getCode();

        // 4. 查询可用座位
        Seat availableSeat = seatMapper.getAvailableSeat(
                train.getId(),
                seatCode
        );
        if (availableSeat == null) {
            throw new CustomException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "该车次无可用 " + seatTypeName);
        }

        // 5. 更新座位状态（乐观锁）
        int updated = seatMapper.updateSeatStatusAndVersion(
                availableSeat.getId(),
                availableSeat.getVersion()
        );
        if (updated == 0) {
            throw new CustomException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "座位已被占用");
        }

        // 6. 创建订单
        Order order = new Order();
        order.setUserId(user.getId());
        order.setTrainId(train.getId());
        order.setSeatId(availableSeat.getId());
        order.setSeatType(seatCode);
        order.setOrderTime(LocalDateTime.now());
        // 已支付
        order.setStatus(1);
        orderMapper.insertOrderInfo(order);
        return ApiResponse.success("恭喜你,购票成功!", null);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseEntity changeOrder(Long originalOrderId, Long newTrainId, Integer newCarriageNumber, String newSeatNumber) {
        // 1. 获取原订单信息
        Order originalOrder = orderMapper.selectById(originalOrderId);
        if (originalOrder == null || originalOrder.getStatus() != 1) {
            throw new CustomException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "订单不存在或未支付");
        }

        // 2. 获取原车次信息（获取出发站）
        Train originalTrain = trainMapper.getTrainById(originalOrder.getTrainId());
        if (originalTrain == null) {
            throw new CustomException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "原订单车次信息不存在");
        }

        // 3. 校验改签时间（如发车前24小时）
        LocalTime departureTime = trainMapper.getDepartureTime(originalOrder.getTrainId());
        if (departureTime.isBefore(LocalTime.now().plusHours(1))) {
            throw new CustomException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "已过改签时间");
        }

        // 4. 获取新车次信息
        Train newTrain = trainMapper.getTrainById(newTrainId);
//        if (newTrain == null ||
//                !newTrain.getDepartureStation().equals(originalTrain.getDepartureStation())) {
//            throw new RuntimeException("目标车次不符合要求");
//        }
        if (newTrain == null) {
            throw new CustomException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "目标车次不符合要求");
        }

        // 假设通过车次和车厢号查询目标车厢信息
        Carriage targetCarriage = carriageMapper.selectByTrainIdAndCarriageNumber(
                newTrainId, newCarriageNumber
        );

        if (targetCarriage == null) {
            throw new CustomException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "目标车厢不可用");
        }

        // 5. 检查目标座位是否可用
        Seat newSeat = seatMapper.selectAvailableSeat(newTrainId, targetCarriage.getCarriageNumber(), newSeatNumber);
        if (newSeat == null || newSeat.getStatus() != 0) {
            throw new CustomException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "目标座位不可用");
        }

        // 6. 计算手续费和差价
        BigDecimal changeFee = calculateChangeFee(originalTrain, departureTime);
        BigDecimal priceDiff = newTrain.getPrice().subtract(originalTrain.getPrice());

        // 7. 更新原订单状态// 3:已改签
        originalOrder.setStatus(3);
        originalOrder.setIsChanged(1);
        orderMapper.updateById(originalOrder);

        // 8. 创建新订单（无需 price 字段，但需关联新车次）
        Order newOrder = new Order();
        newOrder.setUserId(originalOrder.getUserId());
        newOrder.setSeatId(newSeat.getId());
        newOrder.setSeatType(newSeat.getSeatType());
        newOrder.setTrainId(newTrainId);
        newOrder.setOriginalOrderId(originalOrderId);
        newOrder.setOrderTime(LocalDateTime.now());
        // 已支付
        newOrder.setStatus(1);

        orderMapper.insert(newOrder);

        // 9. 更新目标座位状态// 1:已售
        newSeat.setStatus(1);
        newSeat.setVersion(1);
        seatMapper.updateById(newSeat);

        // 10. 记录改签信息
        TicketChange ticketChange = new TicketChange();
        ticketChange.setOriginalOrderId(originalOrderId);
        ticketChange.setNewOrderId(newOrder.getId());
        ticketChange.setNewSeatId(newSeat.getId());
        ticketChange.setNewTrainId(newTrainId);
        ticketChange.setChangeFee(changeFee);
        ticketChange.setPriceDiff(priceDiff);
        ticketChange.setOriginalTrainPrice(originalTrain.getPrice());
        ticketChange.setChangeTime(LocalDateTime.now());
        ticketChangeMapper.insert(ticketChange);
        return ApiResponse.success("改签成功", null);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseEntity refundOrder(Long orderId) {
        // 1. 获取订单信息
        Order originalOrder = orderMapper.selectById(orderId);
        if (originalOrder == null || originalOrder.getStatus() != 1) {
            throw new CustomException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "订单不存在或未支付");
        }
        // 2. 获取原车次发车时间
        LocalTime departureTime = trainMapper.getDepartureTime(originalOrder.getTrainId());
        if (departureTime == null) {
            throw new CustomException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "车次发车时间信息不存在");
        }
        // 3. 计算退票手续费
        //  double refundFee = calculateRefundFee(departureTime);
        //  double refundAmount = originalOrder.getPrice() - refundFee;

        Train trainInfo = trainMapper.getTrainById(originalOrder.getTrainId());
        if (trainInfo == null) {
            throw new CustomException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "车次信息不存在");
        }
        // 4. 更新订单状态// 2:已退款
        originalOrder.setStatus(2);
        originalOrder.setRefundFee(trainInfo.getPrice().multiply(new BigDecimal("0.8")));
        originalOrder.setRefundTime(LocalDateTime.now());
        orderMapper.updateRefundInfoById(originalOrder);

        // 5. 释放座位（根据业务需求）
        Seat seat = seatMapper.selectSeatById(originalOrder.getSeatId());
        // 0:可用
        seat.setStatus(0);
        seatMapper.updateById(seat);

        // 6. 退款处理（调用支付接口）
        return ApiResponse.success("退票成功", null);
    }

    @Override
    public ResponseEntity listOrderInfo() {
        List<OrderDTO> list = orderMapper.listOrders();
        return ApiResponse.success("获取订单成功", list);
    }

    @Override
    public BookingDetailsDTO getBookingDetailsByRealNameAndTrainNumber(String realName, String trainNumber) {
        return orderMapper.selectBookingDetailsByRealNameAndTrainNumber(realName, trainNumber);
    }

    private BigDecimal calculateChangeFee(Train originalTrain, LocalTime departureTime) {
        // 计算当前时间到发车时间的剩余分钟数
        long hoursBeforeDeparture = ChronoUnit.HOURS.between(LocalTime.now(), departureTime);

        // 根据剩余时间计算手续费比例
        BigDecimal feeRate;
        if (hoursBeforeDeparture >= 24) {
            // 5% 手续费
            feeRate = new BigDecimal("0.05");
        } else {
            // 10% 手续费
            feeRate = new BigDecimal("0.10");
        }

        // 计算手续费金额（基于原车次票价）
        return originalTrain.getPrice().multiply(feeRate);
    }
}
